package com.zhsm.fuxi.mapmanager.MapStrategy;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.TextUtils;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.TextureMapView;
import com.baidu.mapapi.model.LatLng;
import com.zhsm.paipaiout.baselibrary.utils.UIUtils;
import com.zhsm.fuxi.mapmanager.mark.MarkConfig;

/**
 * 这里只将Mark的设置用建造者模式构建了
 * 定位没有提出去是因为这些类都是百度独有的
 */

public class BaiduMapStrategy implements BaseMapLoaderStrategy {

    private LocationClient mLocationClient;
    private Bitmap mBitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
    private LocationListener listener;

    public BaiduMapStrategy() {
    }

    @Override
    public void initLocation(Context context) {
        if (context == null) throw new IllegalStateException("context is required");
        mLocationClient = new LocationClient(context);
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        //可选，默认高精度，设置定位模式，高精度，低功耗，仅设备
        option.setCoorType("gcj02");
        //可选，默认gcj02，设置返回的定位结果坐标系
        int span = 3000;
        option.setScanSpan(span);
        //可选，默认0，即仅定位一次，设置发起定位请求的间隔需要大于等于1000ms才是有效的
        option.setIsNeedAddress(true);
        //可选，设置是否需要地址信息，默认不需要
        option.setOpenGps(true);
        //可选，默认false,设置是否使用gps
        option.setLocationNotify(true);
        //可选，默认false，设置是否当GPS有效时按照1S/1次频率输出GPS结果
        option.setIsNeedLocationDescribe(true);
        //可选，默认false，设置是否需要位置语义化结果，可以在BDLocation.getLocationDescribe里得到，结果类似于“在北京天安门附近”
        option.setIsNeedLocationPoiList(true);
        //可选，默认false，设置是否需要POI结果，可以在BDLocation.getPoiList里得到
        option.setIgnoreKillProcess(false);
        //可选，默认true，定位SDK内部是一个SERVICE，并放到了独立进程，设置是否在stop的时候杀死这个进程，默认不杀死
        option.SetIgnoreCacheException(false);
        //可选，默认false，设置是否收集CRASH信息，默认收集
        option.setEnableSimulateGps(false);
        //可选，默认false，设置是否需要过滤GPS仿真结果，默认需要
        mLocationClient.setLocOption(option);
    }


    @Override
    public void startLocation(LocationCallBack callBack) {
        if (listener == null) {
            listener = new LocationListener();
        }
        listener.setLocationCallBack(callBack);
        mLocationClient.registerLocationListener(listener);
        mLocationClient.start();

    }

    @Override
    public void stopLocation() {
        if (mLocationClient.isStarted()) {
            mLocationClient.stop();
        }
        cleanListener();
    }

    @Override
    public Marker addMarkBitmap(TextureMapView mapView, MarkConfig config) {

        if (config.getImageResId() == 0) throw new IllegalStateException("ImageResId is required");
        if (config.getImageWidth() == 0)
            throw new IllegalStateException("ImageWidth is required and  ImageWidth must be greater than zero");
        if (config.getImageHeight() == 0)
            throw new IllegalStateException("ImageHeight is required and  ImageHeight must be greater than zero");

        BitmapDescriptor bitmapMarker = BitmapDescriptorFactory.fromBitmap(
                getBitMap(mapView.getContext(), config.getImageResId(),
                        config.getImageWidth(), config.getImageHeight()));
        MarkerOptions option = new MarkerOptions()
                .position(config.getLatLng())
                .icon(bitmapMarker);
        if (config.getExtraInfo() != null) {
            option.extraInfo(config.getExtraInfo());
        }
        if (!TextUtils.isEmpty(config.getTitle())) {
            option.title(config.getTitle());
        }
        return (Marker) getBaiduMap(mapView).addOverlay(option);
    }

    private BaiduMap getBaiduMap(TextureMapView mapView) {
        return mapView.getMap();
    }

    @Override
    public Marker addMarkView(TextureMapView mapView, MarkConfig config) {
        if (config.getMarkView() == null) throw new IllegalStateException("View is required");
        MarkerOptions options = new MarkerOptions();
        BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromView(config.getMarkView());
        options.animateType(MarkerOptions.MarkerAnimateType.grow);
        options.icon(bitmapDescriptor)
                .position(config.getLatLng());
        if (!TextUtils.isEmpty(config.getTitle())) {
            options.title(config.getTitle());
        }
        if (config.getExtraInfo() != null) {
            options.extraInfo(config.getExtraInfo());
        }
//                .rotate(360f).draggable(true).period(10);
        return (Marker) getBaiduMap(mapView).addOverlay(options);
    }

    @Override
    public Object getMark(TextureMapView mapView, MarkConfig config) {

        MarkerOptions options = new MarkerOptions();
        try {
            if (config.getMarkView() != null) {
                BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromView(config.getMarkView());
                options.icon(bitmapDescriptor);
            } else if (config.getImageResId() != 0) {
                BitmapDescriptor bitmapMarker = BitmapDescriptorFactory.fromBitmap(
                        getBitMap(mapView.getContext(), config.getImageResId(),
                                config.getImageWidth(), config.getImageHeight()));
                options.icon(bitmapMarker);
            }

            options.position(config.getLatLng());
            if (!TextUtils.isEmpty(config.getTitle())) {
                options.title(config.getTitle());
            }
            if (config.getExtraInfo() != null) {
                options.extraInfo(config.getExtraInfo());
            }
        } catch (Exception e) {
            //这里有可能context是一个空对象，例如在创建完marker之前销毁了activity
            e.printStackTrace();
        }

        return options;
    }

    @Override
    public void recycle() {
        mBitmap.recycle();
        if (mLocationClient == null) {
            return;
        }
        if (mLocationClient.isStarted()) {
            mLocationClient.stop();
        }
        cleanListener();
        listener = null;
    }

    private void cleanListener() {
//        mLocationClient.unRegisterLocationListener(listener);
        if (listener != null) {
            listener.setLocationCallBack(null);
        }
    }

    private Bitmap getBitMap(Context context, int imgResId, int imgW, int imgH) {
        mBitmap = Bitmap.createScaledBitmap(
                BitmapFactory.decodeResource(context.getResources(), imgResId)
                , UIUtils.dip2px(context, imgW)
                , UIUtils.dip2px(context, imgH)
                , true);
        return mBitmap;
    }

    @Override
    public void setLocationDirectationMarker(LatLng location, float direction, BaiduMap baiduMap) {
        // 构造定位数据
        MyLocationData locData = new MyLocationData.Builder()
                .accuracy(16f)
                // 此处设置开发者获取到的方向信息，顺时针0-360
                .direction(direction)
                .latitude(location.latitude)
                .longitude(location.longitude)
                .build();
        // 设置定位数据
        baiduMap.setMyLocationData(locData);
    }

    class LocationListener implements BDLocationListener {

        private LocationCallBack mLocationCallBack;

        public void setLocationCallBack(LocationCallBack locationCallback) {
            this.mLocationCallBack = locationCallback;
        }

        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
            int errorCode = bdLocation.getLocType();

            if (errorCode != 61 && errorCode != 65 && errorCode != 161) {//61 GPS定位结果，GPS定位成功。//65 定位缓存的结果。161 网络定位结果，网络定位定位成功。
                if (mLocationCallBack != null) {
                    //失败后的回调
                    mLocationCallBack.onLocationFail(bdLocation);
                }
                return;
            }
            if (mLocationCallBack != null) {
                //成功后的回调
                mLocationCallBack.onLocationSuccess(bdLocation);
            }
        }
    }
}
